home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16_Src.lha / Python16_Source / Objects / rangeobject.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-10  |  4.1 KB  |  237 lines

  1. /* Range object implementation */
  2.  
  3. #include "Python.h"
  4.  
  5. typedef struct {
  6.     PyObject_HEAD
  7.     long    start;
  8.     long    step;
  9.     long    len;
  10.     int    reps;
  11. } rangeobject;
  12.  
  13. #include "protos/rangeobject.h"
  14.  
  15.  
  16. PyObject *
  17. PyRange_New(start, len, step, reps)
  18.     long start, len, step;
  19.     int reps;
  20. {
  21.     rangeobject *obj = PyObject_NEW(rangeobject, &PyRange_Type);
  22.  
  23.     obj->start = start;
  24.     obj->len   = len;
  25.     obj->step  = step;
  26.     obj->reps  = reps;
  27.  
  28.     return (PyObject *) obj;
  29. }
  30.  
  31. static void
  32. range_dealloc(r)
  33.     rangeobject *r;
  34. {
  35.     PyObject_DEL(r);
  36. }
  37.  
  38. static PyObject *
  39. range_item(r, i)
  40.     rangeobject *r;
  41.     int i;
  42. {
  43.     if (i < 0 || i >= r->len * r->reps) {
  44.         PyErr_SetString(PyExc_IndexError,
  45.                 "xrange object index out of range");
  46.         return NULL;
  47.     }
  48.  
  49.     return PyInt_FromLong(r->start + (i % r->len) * r->step);
  50. }
  51.  
  52. static int
  53. range_length(r)
  54.     rangeobject *r;
  55. {
  56.     return r->len * r->reps;
  57. }
  58.  
  59. static int
  60. range_print(r, fp, flags)
  61.     rangeobject *r;
  62.     FILE *fp;
  63.     int flags;
  64. {
  65.     int i, j;
  66.  
  67.     fprintf(fp, "(");
  68.     for (i = 0; i < r->reps; ++i)
  69.         for (j = 0; j < r->len; ++j) {
  70.             if (j > 0 || i > 0)
  71.                 fprintf(fp, ", ");
  72.  
  73.             fprintf(fp, "%ld", r->start + j * r->step);
  74.         }
  75.  
  76.     if (r->len == 1 && r->reps == 1)
  77.         fprintf(fp, ",");
  78.     fprintf(fp, ")");
  79.     return 0;
  80. }
  81.  
  82. static PyObject *
  83. range_repr(r)
  84.     rangeobject *r;
  85. {
  86.     char buf[80];
  87.     sprintf(buf, "(xrange(%ld, %ld, %ld) * %d)",
  88.             r->start,
  89.             r->start + r->len * r->step,
  90.             r->step,
  91.             r->reps);
  92.     return PyString_FromString(buf);
  93. }
  94.  
  95. static PyObject *
  96. range_concat(r, obj)
  97.     rangeobject *r;
  98.     PyObject *obj;
  99. {
  100.     PyErr_SetString(PyExc_TypeError, "cannot concatenate xrange objects");
  101.     return NULL;
  102. }
  103.  
  104. static PyObject *
  105. range_repeat(r, n)
  106.     rangeobject *r;
  107.     int n;
  108. {
  109.     if (n < 0)
  110.         return (PyObject *) PyRange_New(0, 0, 1, 1);
  111.  
  112.     else if (n == 1) {
  113.         Py_INCREF(r);
  114.         return (PyObject *) r;
  115.     }
  116.  
  117.     else
  118.         return (PyObject *) PyRange_New(
  119.                         r->start,
  120.                         r->len,
  121.                         r->step,
  122.                         r->reps * n);
  123. }
  124.  
  125. static int
  126. range_compare(r1, r2)
  127.     rangeobject *r1, *r2;
  128. {
  129.     if (r1->start != r2->start)
  130.         return r1->start - r2->start;
  131.  
  132.     else if (r1->step != r2->step)
  133.         return r1->step - r2->step;
  134.  
  135.     else if (r1->len != r2->len)
  136.         return r1->len - r2->len;
  137.  
  138.     else
  139.         return r1->reps - r2->reps;
  140. }
  141.  
  142. static PyObject *
  143. range_slice(r, low, high)
  144.     rangeobject *r;
  145.     int low, high;
  146. {
  147.     if (r->reps != 1) {
  148.         PyErr_SetString(PyExc_TypeError,
  149.                 "cannot slice a replicated xrange");
  150.         return NULL;
  151.     }
  152.     if (low < 0)
  153.         low = 0;
  154.     else if (low > r->len)
  155.         low = r->len;
  156.     if (high < 0)
  157.         high = 0;
  158.     if (high < low)
  159.         high = low;
  160.     else if (high > r->len)
  161.         high = r->len;
  162.  
  163.     if (low == 0 && high == r->len) {
  164.         Py_INCREF(r);
  165.         return (PyObject *) r;
  166.     }
  167.  
  168.     return (PyObject *) PyRange_New(
  169.                 low * r->step + r->start,
  170.                 high - low,
  171.                 r->step,
  172.                 1);
  173. }
  174.  
  175. static PyObject *
  176. range_tolist(self, args)
  177. rangeobject *self;
  178. PyObject *args;
  179. {
  180.     PyObject *thelist;
  181.     int j;
  182.     int len = self->len * self->reps;
  183.  
  184.     if (! PyArg_Parse(args, ""))
  185.         return NULL;
  186.  
  187.     if ((thelist = PyList_New(len)) == NULL)
  188.         return NULL;
  189.  
  190.     for (j = 0; j < len; ++j)
  191.         if ((PyList_SetItem(thelist, j, (PyObject *) PyInt_FromLong(
  192.             self->start + (j % self->len) * self->step))) < 0)
  193.             return NULL;
  194.  
  195.     return thelist;
  196. }
  197.  
  198. static PyObject *
  199. range_getattr(r, name)
  200.     rangeobject *r;
  201.     char *name;
  202. {
  203.     static PyMethodDef range_methods[] = {
  204.         {"tolist",    (PyCFunction)range_tolist},
  205.         {NULL,        NULL}
  206.     };
  207.  
  208.     return Py_FindMethod(range_methods, (PyObject *) r, name);
  209. }
  210.  
  211. static PySequenceMethods range_as_sequence = {
  212.     (inquiry)range_length, /*sq_length*/
  213.     (binaryfunc)range_concat, /*sq_concat*/
  214.     (intargfunc)range_repeat, /*sq_repeat*/
  215.     (intargfunc)range_item, /*sq_item*/
  216.     (intintargfunc)range_slice, /*sq_slice*/
  217.     0,        /*sq_ass_item*/
  218.     0,        /*sq_ass_slice*/
  219. };
  220.  
  221. PyTypeObject PyRange_Type = {
  222.     PyObject_HEAD_INIT(&PyType_Type)
  223.     0,            /* Number of items for varobject */
  224.     "xrange",        /* Name of this type */
  225.     sizeof(rangeobject),    /* Basic object size */
  226.     0,            /* Item size for varobject */
  227.     (destructor)range_dealloc, /*tp_dealloc*/
  228.     (printfunc)range_print, /*tp_print*/
  229.     (getattrfunc)range_getattr, /*tp_getattr*/
  230.     0,            /*tp_setattr*/
  231.     (cmpfunc)range_compare, /*tp_compare*/
  232.     (reprfunc)range_repr, /*tp_repr*/
  233.     0,            /*tp_as_number*/
  234.     &range_as_sequence,    /*tp_as_sequence*/
  235.     0,            /*tp_as_mapping*/
  236. };
  237.